home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / elm2.2 / part19 < prev    next >
Encoding:
Internet Message Format  |  1989-04-12  |  49.4 KB

  1. Subject:  v18i098:  Elm mail system, release 2.2, Part19/22
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
  7. Posting-number: Volume 18, Issue 98
  8. Archive-name: elm2.2/part19
  9.  
  10. #!/bin/sh
  11. # this is part 19 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file src/read_rc.c continued
  14. #
  15. CurArch=19
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file src/read_rc.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> src/read_rc.c
  27. X          strcpy(raw_recvdmail, word2);
  28. X          expand_env(recvd_mail, word2);
  29. X          last = NOTWEEDOUT;
  30. X        }
  31. X        else if (equal(word1, "editor") || equal(word1,"mailedit")) {
  32. X          strcpy(raw_editor, word2);
  33. X          expand_env(editor, word2);
  34. X          last = NOTWEEDOUT;
  35. X        }
  36. X        else if (equal(word1, "sentmail") ||
  37. X        equal(word1, "savemail") || equal(word1, "saveto")) {
  38. X          /* the last two were old names of this option - here for
  39. X           * compatibility in case the user has never written out
  40. X           * a new elmrc while in elm since the name change.
  41. X           */
  42. X          rc_has_sentmail = TRUE;
  43. X          strcpy(raw_sentmail, word2);
  44. X          expand_env(sent_mail, word2);
  45. X          last = NOTWEEDOUT;
  46. X        }
  47. X        else if (equal(word1, "calendar")) {
  48. X          strcpy(raw_calendar_file, word2);
  49. X          expand_env(calendar_file, word2);
  50. X          last = NOTWEEDOUT;
  51. X        }
  52. X        else if (equal(word1, "print") || equal(word1, "printmail")) {
  53. X          strcpy(raw_printout, word2);
  54. X          expand_env(printout, word2);
  55. X          last = NOTWEEDOUT;
  56. X        }
  57. X        else if (equal(word1, "pager") || equal(word1, "page")) {
  58. X          strcpy(raw_pager, word2);
  59. X          expand_env(pager, word2);
  60. X          if (equal(pager,"builtin+") || equal(pager,"internal+"))
  61. X        clear_pages++;
  62. X          last = NOTWEEDOUT;
  63. X        }
  64. X        else if (equal(word1, "signature")) {
  65. X          if (equal(shift_lower(word2), "on") ||
  66. X          equal(shift_lower(word2), "off")) {
  67. X        errors++;
  68. X        printf(
  69. X    "\"signature\" used in obsolete way in .elm/elmrc file. Ignored!\n\r");
  70. X        printf(
  71. X "\t(Signature should specify the filename to use rather than on/off.)\n\r\n");
  72. X          }
  73. X          else {
  74. X        strcpy(raw_local_signature, word2);
  75. X        strcpy(raw_remote_signature, raw_local_signature);
  76. X        expand_env(local_signature, word2);
  77. X        strcpy(remote_signature, local_signature);
  78. X          }
  79. X          last = NOTWEEDOUT;
  80. X        }
  81. X        else if (equal(word1, "localsignature")) {
  82. X          strcpy(raw_local_signature, word2);
  83. X          expand_env(local_signature, word2);
  84. X          last = NOTWEEDOUT;
  85. X        }
  86. X        else if (equal(word1, "remotesignature")) {
  87. X          strcpy(raw_remote_signature, word2);
  88. X          expand_env(remote_signature, word2);
  89. X          last = NOTWEEDOUT;
  90. X        }
  91. X        else if (equal(word1, "escape")) {
  92. X          escape_char = word2[0];
  93. X          last = NOTWEEDOUT;
  94. X        }
  95. X        else if (equal(word1, "autocopy")) {
  96. X          auto_copy = is_it_on(word2);
  97. X          last = NOTWEEDOUT;
  98. X        }
  99. X        else if (equal(word1, "copy") || equal(word1, "auto_cc")) {
  100. X          auto_cc = is_it_on(word2);
  101. X          last = NOTWEEDOUT;
  102. X        }
  103. X        else if (equal(word1, "names")) {
  104. X          names_only = is_it_on(word2);
  105. X          last = NOTWEEDOUT;
  106. X        }
  107. X        else if (equal(word1, "resolve")) {
  108. X          resolve_mode = is_it_on(word2);
  109. X          last = NOTWEEDOUT;
  110. X        }
  111. X        else if (equal(word1, "weed")) {
  112. X          filter = is_it_on(word2);
  113. X          last = NOTWEEDOUT;
  114. X        }
  115. X        else if (equal(word1, "noheader")) {
  116. X          noheader = is_it_on(word2);
  117. X          last = NOTWEEDOUT;
  118. X        }
  119. X        else if (equal(word1, "titles")) {
  120. X          title_messages = is_it_on(word2);
  121. X          last = NOTWEEDOUT;
  122. X        }
  123. X        else if (equal(word1, "savebyname") || equal(word1, "savename")) {
  124. X          save_by_name = is_it_on(word2);
  125. X          last = NOTWEEDOUT;
  126. X        }
  127. X        else if (equal(word1, "movepage") || equal(word1, "page") ||
  128. X             equal(word1, "movewhenpaged")) {
  129. X          move_when_paged = is_it_on(word2);
  130. X          last = NOTWEEDOUT;
  131. X        }
  132. X        else if (equal(word1, "pointnew") || equal(word1, "pointtonew")) {
  133. X          point_to_new = is_it_on(word2);
  134. X          last = NOTWEEDOUT;
  135. X        }
  136. X        else if (equal(word1, "keypad") || equal(word1, "hpkeypad")) {
  137. X          hp_terminal = is_it_on(word2);
  138. X          last = NOTWEEDOUT;
  139. X        }
  140. X        else if (equal(word1, "softkeys") || equal(word1, "hpsoftkeys")) {
  141. X          if (hp_softkeys = is_it_on(word2))
  142. X        hp_terminal = TRUE;    /* must be set also! */
  143. X          last = NOTWEEDOUT;
  144. X        }
  145. X        else if (equal(word1, "arrow")) {
  146. X          arrow_cursor += is_it_on(word2);    /* may have been set already */
  147. X          last = NOTWEEDOUT;        /* with command line flag -a */
  148. X        }
  149. X        else if (strncmp(word1, "form", 4) == 0) {
  150. X          allow_forms = (is_it_on(word2)? MAYBE : NO);
  151. X          last = NOTWEEDOUT;
  152. X        }
  153. X        else if (equal(word1, "promptafter")) {
  154. X          prompt_after_pager = is_it_on(word2);
  155. X          last = NOTWEEDOUT;
  156. X        }
  157. X        else if (strncmp(word1, "menu", 4) == 0) {
  158. X          /* if not turned off by -m cmd line arg,
  159. X           * obey elmrc file setting */
  160. X          if(mini_menu)
  161. X        mini_menu = is_it_on(word2);
  162. X          last = NOTWEEDOUT;
  163. X        }
  164. X        else if (strncmp(word1, "warning", 7) == 0) {
  165. X          warnings = is_it_on(word2);
  166. X          last = NOTWEEDOUT;
  167. X        }
  168. X        else if (equal(word1, "alwaysleave")) {
  169. X          /* this is an old option - here for
  170. X           * compatibility in case the user has never written out
  171. X           * a new elmrc while in elm since the split of
  172. X           * alwaysleave into alwayskeep and alwaysstore
  173. X           */
  174. X          always_keep = is_it_on(word2);
  175. X          always_store = !is_it_on(word2);
  176. X          last = NOTWEEDOUT;
  177. X        }
  178. X        else if (equal(word1, "alwayskeep")) {
  179. X          always_keep = is_it_on(word2);
  180. X          last = NOTWEEDOUT;
  181. X        }
  182. X        else if (equal(word1, "alwaysstore") || equal(word1, "store")) {
  183. X          always_store = is_it_on(word2);
  184. X          last = NOTWEEDOUT;
  185. X        }
  186. X        else if (equal(word1, "alwaysdelete") || equal(word1, "delete")) {
  187. X          always_del = is_it_on(word2);
  188. X          last = NOTWEEDOUT;
  189. X        }
  190. X        else if (equal(word1, "askcc") || equal(word1, "cc")) {
  191. X          prompt_for_cc = is_it_on(word2);
  192. X          last = NOTWEEDOUT;
  193. X        }
  194. X        else if (equal(word1, "ask") || equal(word1, "question")) {
  195. X          question_me = is_it_on(word2);
  196. X          last = NOTWEEDOUT;
  197. X        }
  198. X        else if (equal(word1, "keep") || equal(word1, "keepempty")) {
  199. X          keep_empty_files = is_it_on(word2);
  200. X          last = NOTWEEDOUT;
  201. X        }
  202. X        else if (equal(word1, "bounce") || equal(word1, "bounceback")) {
  203. X          bounceback = atoi(word2);
  204. X          if (bounceback > MAX_HOPS) {
  205. X        errors++;
  206. X        printf(
  207. X    "Warning: bounceback is set to greater than %d (max-hops). Ignored.\n",
  208. X             MAX_HOPS);
  209. X        bounceback = 0;
  210. X          }
  211. X          last = NOTWEEDOUT;
  212. X        }
  213. X        else if (equal(word1, "userlevel")) {
  214. X          user_level = atoi(word2);
  215. X          last = NOTWEEDOUT;
  216. X        }
  217. X        else if (equal(word1, "timeout")) {
  218. X          timeout = atoi(word2);
  219. X          if (timeout < 10) {
  220. X        errors++;
  221. X        printf(
  222. X         "Warning: timeout is set to less than 10 seconds. Ignored.\n");
  223. X        timeout = 0;
  224. X          }
  225. X          last = NOTWEEDOUT;
  226. X        }
  227. X        else if (equal(word1, "weedout")) {
  228. X          weedout(word2);
  229. X          last = WEEDOUT;
  230. X        }
  231. X        else if (equal(word1, "alternatives")) {
  232. X          alternatives(word2);
  233. X          last = ALTERNATIVES;
  234. X        }
  235. X        else if (last == WEEDOUT)    /* could be multiple line weedout */
  236. X          weedout(buffer);
  237. X        else if (last == ALTERNATIVES)    /* multi-line addresses   */
  238. X          alternatives(buffer);
  239. X        else {
  240. X          errors++;
  241. X          printf(
  242. X         "I can't understand line %d in your \".elm/elmrc\" file:\n> %s\n", 
  243. X             lineno, buffer);
  244. X        }
  245. X      }
  246. X      /* sleep two seconds for each error and then some so user
  247. X       * can read them before screen is cleared */
  248. X      if(errors)
  249. X        sleep((errors * 2) + 2);
  250. X    }
  251. X
  252. X    /* see if the user has a folders directory */
  253. X    if (access(folders, 00) == -1) {
  254. X      if(batch_only)  {
  255. X        printf("\n\rNotice:\
  256. X\n\rELM requires the use of a folders directory to store your mail folders in.\
  257. X\n\rI'd like to create the directory %s for you,\
  258. X\n\rbut I can't in \"batch mode\". Please run ELM in \"normal mode\" first.\
  259. X\n\r", folders);
  260. X        exit(0);
  261. X      }
  262. X
  263. X      printf("\n\rNotice:\
  264. X\n\rELM requires the use of a folders directory to store your mail folders in.\
  265. X\n\rShall I create the directory %s for you (y/n)? y%c", folders, BACKSPACE);
  266. X
  267. X      fflush(stdout);
  268. X      ch=getchar();
  269. X      if (ch == 'n' || ch == 'N') {
  270. X        printf("No.\n\rVery well. I won't create it.\
  271. X        \n\rBut, you may run into difficulties later.\n\r");
  272. X        sleep(4);
  273. X      }
  274. X      else {
  275. X        printf("Yes.\n\rGreat! I'll do it now.\n\r");
  276. X        create_new_folders();
  277. X      }
  278. X    }
  279. X
  280. X    /* If recvd_mail or sent_mail havent't yet been established in
  281. X     * the elmrc, establish them from their defaults.
  282. X     * Then if they begin with a metacharacter, replace it with the
  283. X     * folders directory name.
  284. X     */
  285. X    if(!rc_has_recvdmail) {
  286. X      strcpy(raw_recvdmail, default_recvdmail);
  287. X      strcpy(recvd_mail, raw_recvdmail);
  288. X    }
  289. X    if(metachar(recvd_mail[0])) {
  290. X      strcpy(buffer, &recvd_mail[1]);
  291. X      sprintf(recvd_mail, "%s/%s", folders, buffer);
  292. X    }
  293. X
  294. X    if(!rc_has_sentmail) {
  295. X      sprintf(raw_sentmail, default_sentmail);
  296. X      sprintf(sent_mail, default_sentmail);
  297. X    }
  298. X    if(metachar(sent_mail[0])) {
  299. X      strcpy(buffer, &sent_mail[1]);
  300. X      sprintf(sent_mail, "%s/%s", folders, buffer);
  301. X    }
  302. X
  303. X    if (debug > 10)     /** only do this if we REALLY want debug! **/
  304. X      dump_rc_results();
  305. X
  306. X}
  307. X    
  308. Xweedout(string)
  309. Xchar *string;
  310. X{
  311. X    /** This routine is called with a list of headers to weed out.   **/
  312. X
  313. X    char *strptr, *header;
  314. X    register int i;
  315. X
  316. X    strptr = string;
  317. X
  318. X    while ((header = strtok(strptr, "\t ,\"'")) != NULL) {
  319. X      if (strlen(header) > 0) {
  320. X        if (! strcmp(header, "*end-of-user-headers*")) break;
  321. X        if (weedcount > MAX_IN_WEEDLIST) {
  322. X          printf("Too many weed headers!  Leaving...\n");
  323. X          exit(1);
  324. X        }
  325. X        if ((weedlist[weedcount] = pmalloc(strlen(header) + 1)) 
  326. X        == NULL) {
  327. X          printf("Too many weed headers! Out of memory!  Leaving...\n");
  328. X          exit(1);
  329. X        }
  330. X
  331. X        for (i=0; i< strlen(header); i++)
  332. X          if (header[i] == '_') header[i] = ' ';
  333. X
  334. X        strcpy(weedlist[weedcount], header);
  335. X        weedcount++;
  336. X      }
  337. X      strptr = NULL;
  338. X    }
  339. X}
  340. X
  341. Xalternatives(string)
  342. Xchar *string;
  343. X{
  344. X    /** This routine is called with a list of alternative addresses
  345. X        that you may receive mail from (forwarded) **/
  346. X
  347. X    char *strptr, *address;
  348. X    struct addr_rec *current_record, *previous_record;
  349. X
  350. X    previous_record = alternative_addresses;    /* start 'er up! */
  351. X    /* move to the END of the alternative addresses list */
  352. X
  353. X    if (previous_record != NULL)
  354. X      while (previous_record->next != NULL)
  355. X        previous_record = previous_record->next;
  356. X
  357. X    strptr = (char *) string;
  358. X
  359. X    while ((address = strtok(strptr, "\t ,\"'")) != NULL) {
  360. X      if (previous_record == NULL) {
  361. X        previous_record = (struct addr_rec *) pmalloc(sizeof 
  362. X        *alternative_addresses);
  363. X
  364. X        strcpy(previous_record->address, address);
  365. X        previous_record->next = NULL;
  366. X        alternative_addresses = previous_record;
  367. X      }
  368. X      else {
  369. X        current_record = (struct addr_rec *) pmalloc(sizeof 
  370. X        *alternative_addresses);
  371. X      
  372. X        strcpy(current_record->address, address);
  373. X        current_record->next = NULL;
  374. X        previous_record->next = current_record;
  375. X        previous_record = current_record;
  376. X      }
  377. X      strptr = (char *) NULL;
  378. X    }
  379. X}
  380. X
  381. Xdefault_weedlist()
  382. X{
  383. X    /** Install the default headers to weed out!  Many gracious 
  384. X        thanks to John Lebovitz for this dynamic method of 
  385. X        allocation!
  386. X    **/
  387. X
  388. X    static char *default_list[] = { ">From", "In-Reply-To:",
  389. X               "References:", "Newsgroups:", "Received:",
  390. X               "Apparently-To:", "Message-Id:", "Content-Type:",
  391. X               "From", "X-Mailer:", "Status:",
  392. X               "*end-of-defaults*", NULL
  393. X             };
  394. X
  395. X    for (weedcount = 0; default_list[weedcount] != (char *) 0;weedcount++){
  396. X      if ((weedlist[weedcount] = 
  397. X          pmalloc(strlen(default_list[weedcount]) + 1)) == NULL) {
  398. X        printf("\n\rNot enough memory for default weedlist. Leaving.\n\r");
  399. X        leave(1);
  400. X      }
  401. X      strcpy(weedlist[weedcount], default_list[weedcount]);
  402. X    }
  403. X}
  404. X
  405. Xint
  406. Xmatches_weedlist(buffer)
  407. Xchar *buffer;
  408. X{
  409. X    /** returns true iff the first 'n' characters of 'buffer' 
  410. X        match an entry of the weedlist **/
  411. X    
  412. X    register int i;
  413. X
  414. X    for (i=0;i < weedcount; i++)
  415. X      if (strncmp(buffer, weedlist[i], strlen(weedlist[i])) == 0) 
  416. X        return(1);
  417. X
  418. X    return(0);
  419. X}
  420. X
  421. Xint
  422. Xbreakup(buffer, word1, word2)
  423. Xchar *buffer, *word1, *word2;
  424. X{
  425. X    /** This routine breaks buffer down into word1, word2 where 
  426. X        word1 is alpha characters only, and there is an equal
  427. X        sign delimiting the two...
  428. X        alpha = beta
  429. X        For lines with more than one 'rhs', word2 is set to the
  430. X        entire string.
  431. X        Return -1 if word 2 is of zero length, else 0.
  432. X    **/
  433. X
  434. X    register int i;
  435. X    
  436. X    for (i=0;buffer[i] != '\0' && ok_char(buffer[i]); i++)
  437. X      if (buffer[i] == '_')
  438. X        word1[i] = '-';
  439. X      else if (isupper(buffer[i]))
  440. X        word1[i] = tolower(buffer[i]);
  441. X      else
  442. X        word1[i] = buffer[i];
  443. X
  444. X    word1[i++] = '\0';    /* that's the first word! */
  445. X
  446. X    /** spaces before equal sign? **/
  447. X
  448. X    while (whitespace(buffer[i])) i++;
  449. X    if (buffer[i] == '=') i++;
  450. X
  451. X    /** spaces after equal sign? **/
  452. X
  453. X    while (whitespace(buffer[i])) i++;
  454. X
  455. X    if (buffer[i] != '\0')
  456. X      strcpy(word2, (char *) (buffer + i));
  457. X    else
  458. X      word2[0] = '\0';
  459. X
  460. X    /* remove trailing spaces from word2! */
  461. X    i = strlen(word2) - 1;
  462. X    while(i && (whitespace(word2[i]) || word2[i] == '\n'))
  463. X      word2[i--] = '\0';
  464. X
  465. X    return(*word2 == '\0' ? -1 : 0 );
  466. X
  467. X}
  468. X
  469. Xexpand_env(dest, buffer)
  470. Xchar *dest, *buffer;
  471. X{
  472. X    /** expand possible metacharacters in buffer and then copy
  473. X        to dest... 
  474. X
  475. X        BEWARE!! Because strtok() is used on buffer, buffer may be changed.
  476. X
  477. X        This routine knows about "~" being the home directory,
  478. X        and "$xxx" being an environment variable.
  479. X    **/
  480. X
  481. X    char  *word, *string, next_word[SLEN];
  482. X    
  483. X    if (buffer[0] == '/') {
  484. X      dest[0] = '/';
  485. X      dest[1] = '\0';
  486. X    }
  487. X    else
  488. X      dest[0] = '\0';
  489. X
  490. X    string = (char *) buffer;
  491. X
  492. X    while ((word = strtok(string, "/")) != NULL) {
  493. X      if (word[0] == '$') {
  494. X        next_word[0] = '\0';
  495. X        if (getenv((char *) (word + 1)) != NULL)
  496. X        strcpy(next_word, getenv((char *) (word + 1)));
  497. X        if (strlen(next_word) == 0)
  498. X          leave(printf("\n\rCan't expand environment variable '%s'.\n\r",
  499. X            word));
  500. X      }
  501. X      else if (word[0] == '~' && word[1] == '\0')
  502. X        strcpy(next_word, home);
  503. X      else
  504. X        strcpy(next_word, word);
  505. X
  506. X      sprintf(dest, "%s%s%s", dest, 
  507. X         (strlen(dest) > 0 && lastch(dest) != '/' ? "/":""),
  508. X         next_word);
  509. X
  510. X      string = (char *) NULL;
  511. X    }
  512. X}
  513. X
  514. X#define on_off(s)    (s == 1? "ON " : "OFF")
  515. Xdump_rc_results()
  516. X{
  517. X
  518. X    register int i, len;
  519. X
  520. X    fprintf(debugfile, "folders = %s ", folders);
  521. X    fprintf(debugfile, "recvd_mail = %s ", recvd_mail);
  522. X    fprintf(debugfile, "editor = %s\n", editor);
  523. X    fprintf(debugfile, "printout = %s ", printout);
  524. X    fprintf(debugfile, "sent_mail = %s ", sent_mail);
  525. X    fprintf(debugfile, "calendar_file = %s\n", calendar_file);
  526. X    fprintf(debugfile, "prefixchars = %s ", prefixchars);
  527. X    fprintf(debugfile, "shell = %s ", shell);
  528. X    fprintf(debugfile, "pager = %s\n", pager);
  529. X    fprintf(debugfile, "\n");
  530. X    fprintf(debugfile, "escape = %c\n", escape_char);
  531. X    fprintf(debugfile, "\n");
  532. X
  533. X    fprintf(debugfile, "mini_menu    = %s ", on_off(mini_menu));
  534. X    fprintf(debugfile, "filter_hdrs  = %s ", on_off(filter));
  535. X    fprintf(debugfile, "auto_copy      = %s\n", on_off(auto_copy));
  536. X
  537. X    fprintf(debugfile, "resolve_mode   = %s ", on_off(resolve_mode));
  538. X    fprintf(debugfile, "auto_save_copy = %s ", on_off(auto_cc));
  539. X    fprintf(debugfile, "noheader     = %s\n", on_off(noheader));
  540. X
  541. X    fprintf(debugfile, "title_msgs   = %s ", on_off(title_messages));
  542. X    fprintf(debugfile, "hp_terminal    = %s ", on_off(hp_terminal));
  543. X    fprintf(debugfile, "hp_softkeys    = %s ", on_off(hp_softkeys));
  544. X    fprintf(debugfile, "save_by_name = %s\n", on_off(save_by_name));
  545. X
  546. X    fprintf(debugfile, "move_paged   = %s ", on_off(move_when_paged));
  547. X    fprintf(debugfile, "point_to_new   = %s ", on_off(point_to_new));
  548. X    fprintf(debugfile, "prompt_after_pager   = %s ",
  549. X        on_off(prompt_after_pager));
  550. X    fprintf(debugfile, "bounceback     = %s\n", on_off(bounceback));
  551. X
  552. X    fprintf(debugfile, "always_keep = %s ", on_off(always_keep));
  553. X    fprintf(debugfile, "always_store = %s ", on_off(always_store));
  554. X    fprintf(debugfile, "always_delete  = %s ", on_off(always_del));
  555. X    fprintf(debugfile, "arrow_cursor   = %s ", on_off(arrow_cursor));
  556. X    fprintf(debugfile, "names        = %s\n", on_off(names_only));
  557. X
  558. X    fprintf(debugfile, "warnings     = %s ", on_off(warnings));
  559. X    fprintf(debugfile, "question_me    = %s ", on_off(question_me));
  560. X    fprintf(debugfile, "keep_nil_files = %s\n\n", 
  561. X               on_off(keep_empty_files));
  562. X
  563. X    fprintf(debugfile, "local_signature  = %s\n", local_signature);
  564. X    fprintf(debugfile, "remote_signature = %s\n", remote_signature);
  565. X
  566. X    fprintf(debugfile, "Userlevel is set to %s user: %d\n", 
  567. X        user_level == 0 ? "beginning" : 
  568. X         user_level > 1 ? "expert" : "intermediate", user_level);
  569. X
  570. X    fprintf(debugfile, "\nAnd we're skipping the following headers:\n\t");
  571. X
  572. X    for (len=8, i=0; i < weedcount; i++) {
  573. X      if (weedlist[i][0] == '*') continue;    /* skip '*end-of-defaults*' */
  574. X      if (len + strlen(weedlist[i]) > 80) {
  575. X        fprintf(debugfile, " \n\t");
  576. X        len = 8;
  577. X      }
  578. X      fprintf(debugfile, "%s  ", weedlist[i]);
  579. X      len += strlen(weedlist[i]) + 3;
  580. X    }
  581. X    
  582. X    fprintf(debugfile, "\n\n");
  583. X}
  584. X
  585. Xis_it_on(word)
  586. Xchar *word;
  587. X{
  588. X    /** Returns TRUE if the specified word is either 'ON', 'YES'
  589. X        or 'TRUE', and FALSE otherwise.   We explicitly translate
  590. X        to lowercase here to ensure that we have the fastest
  591. X        routine possible - we really DON'T want to have this take
  592. X        a long time or our startup will be major pain each time.
  593. X    **/
  594. X
  595. X    static char mybuffer[NLEN];
  596. X    register int i, j;
  597. X
  598. X    for (i=0, j=0; word[i] != '\0'; i++)
  599. X      mybuffer[j++] = isupper(word[i]) ? tolower(word[i]) : word[i];
  600. X    mybuffer[j] = '\0';
  601. X
  602. X    return(  (strncmp(mybuffer, "on",   2) == 0) ||
  603. X         (strncmp(mybuffer, "yes",  3) == 0) ||
  604. X         (strncmp(mybuffer, "true", 4) == 0)
  605. X          );
  606. X}
  607. SHAR_EOF
  608. echo "File src/read_rc.c is complete"
  609. chmod 0444 src/read_rc.c || echo "restore of src/read_rc.c fails"
  610. echo "x - extracting src/remail.c (Text)"
  611. sed 's/^X//' << 'SHAR_EOF' > src/remail.c &&
  612. X
  613. Xstatic char rcsid[] = "@(#)$Id: remail.c,v 2.8 89/03/25 21:47:04 syd Exp $";
  614. X
  615. X/*******************************************************************************
  616. X *  The Elm Mail System  -  $Revision: 2.8 $   $State: Exp $
  617. X *
  618. X *             Copyright (c) 1986, 1987 Dave Taylor
  619. X *             Copyright (c) 1988, 1989 USENET Community Trust
  620. X *******************************************************************************
  621. X * Bug reports, patches, comments, suggestions should be sent to:
  622. X *
  623. X *    Syd Weinstein, Elm Coordinator
  624. X *    elm@dsinc.UUCP            dsinc!elm
  625. X *
  626. X *******************************************************************************
  627. X * $Log:    remail.c,v $
  628. X * Revision 2.8  89/03/25  21:47:04  syd
  629. X * Initial 2.2 Release checkin
  630. X * 
  631. X *
  632. X ******************************************************************************/
  633. X
  634. X/** For those cases when you want to have a message continue along
  635. X    to another person in such a way as they end up receiving it with
  636. X    the return address the person YOU received the mail from (does
  637. X    this comment make any sense yet??)...
  638. X
  639. X**/
  640. X
  641. X#include "headers.h"
  642. X#include <errno.h>
  643. X
  644. Xextern int errno;
  645. X
  646. Xchar *error_name(), *error_description();
  647. X
  648. Xint
  649. Xremail()
  650. X{
  651. X    /** remail a message... returns TRUE if new foot needed ... **/
  652. X    
  653. X    FILE *mailfd;
  654. X    char entered[VERY_LONG_STRING], expanded[VERY_LONG_STRING];
  655. X    char *filename, buffer[VERY_LONG_STRING], ch;
  656. X    extern char *tempnam();
  657. X
  658. X    entered[0] = '\0';
  659. X
  660. X    get_to(entered, expanded);
  661. X    if (strlen(entered) == 0)
  662. X      return(0);
  663. X
  664. X    display_to(expanded);
  665. X
  666. X    if((filename=tempnam(temp_dir, "snd.")) == NULL) {
  667. X      dprint(1, (debugfile, "couldn't make temp file nam! (remail)\n"));
  668. X      sprintf(buffer, "Sorry - couldn't make file temp file name.");
  669. X      set_error(buffer);
  670. X      return(1);
  671. X    }
  672. X
  673. X    if ((mailfd = fopen(filename, "w")) == NULL) {
  674. X      dprint(1, (debugfile, "couldn't open temp file %s! (remail)\n", 
  675. X          filename));
  676. X      dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
  677. X          error_description(errno)));
  678. X      sprintf(buffer, "Sorry - couldn't open file %s for writing (%s).",
  679. X          error_name(errno));
  680. X      set_error(buffer);
  681. X      return(1);
  682. X    }
  683. X
  684. X    /** now let's copy the message into the newly opened
  685. X        buffer... **/
  686. X
  687. X    chown (filename, userid, groupid);
  688. X
  689. X    copy_message("", mailfd, FALSE, TRUE, FALSE);  
  690. X
  691. X    fclose(mailfd);
  692. X
  693. X    /** Got the messsage, now let's ensure the person really wants to 
  694. X        remail it... **/
  695. X
  696. X    ClearLine(LINES-1);
  697. X    ClearLine(LINES);
  698. X    PutLine1(LINES-1,0,
  699. X        "Are you sure you want to remail this message (y/n)? y%c",
  700. X        BACKSPACE);
  701. X    fflush(stdin);
  702. X    fflush(stdout);
  703. X    ch = ReadCh();
  704. X    if (tolower(ch) == 'n') { /* another day, another No... */
  705. X      Write_to_screen("No.", 0);
  706. X      set_error("Bounce of message cancelled.");
  707. X          return(1);
  708. X    }
  709. X    Write_to_screen("Yes.", 0);
  710. X
  711. X    sprintf(buffer,"( (%s %s ; %s %s) & ) < %s", 
  712. X          mailer, strip_parens(strip_commas(expanded)), 
  713. X          remove_cmd, filename, filename);
  714. X
  715. X    PutLine0(LINES,0,"Resending mail...");
  716. X    system_call(buffer, SH, FALSE);
  717. X    set_error("Mail resent.");
  718. X
  719. X    return(1);
  720. X}
  721. SHAR_EOF
  722. chmod 0444 src/remail.c || echo "restore of src/remail.c fails"
  723. echo "x - extracting src/reply.c (Text)"
  724. sed 's/^X//' << 'SHAR_EOF' > src/reply.c &&
  725. X
  726. Xstatic char rcsid[] = "@(#)$Id: reply.c,v 2.9 89/03/25 21:47:06 syd Exp $";
  727. X
  728. X/*******************************************************************************
  729. X *  The Elm Mail System  -  $Revision: 2.9 $   $State: Exp $
  730. X *
  731. X *             Copyright (c) 1986, 1987 Dave Taylor
  732. X *             Copyright (c) 1988, 1989 USENET Community Trust
  733. X *******************************************************************************
  734. X * Bug reports, patches, comments, suggestions should be sent to:
  735. X *
  736. X *    Syd Weinstein, Elm Coordinator
  737. X *    elm@dsinc.UUCP            dsinc!elm
  738. X *
  739. X *******************************************************************************
  740. X * $Log:    reply.c,v $
  741. X * Revision 2.9  89/03/25  21:47:06  syd
  742. X * Initial 2.2 Release checkin
  743. X * 
  744. X *
  745. X ******************************************************************************/
  746. X
  747. X/*** routine allows replying to the sender of the current message 
  748. X
  749. X***/
  750. X
  751. X#include "headers.h"
  752. X#include <errno.h>
  753. X
  754. X#ifndef BSD
  755. X#  include <sys/types.h>
  756. X#  include <sys/utsname.h>
  757. X#endif
  758. X
  759. X/** Note that this routine generates automatic header information
  760. X    for the subject and (obviously) to lines, but that these can
  761. X    be altered while in the editor composing the reply message! 
  762. X**/
  763. X
  764. Xchar *strip_parens(), *get_token();
  765. X
  766. Xextern int errno;
  767. X
  768. Xchar *error_name(), *strcat(), *strcpy();
  769. X
  770. Xint
  771. Xreply()
  772. X{
  773. X    /** Reply to the current message.  Returns non-zero iff
  774. X        the screen has to be rewritten. **/
  775. X
  776. X    char return_address[SLEN], subject[SLEN];
  777. X    int  return_value, form_letter;
  778. X
  779. X    form_letter = (headers[current-1]->status & FORM_LETTER);
  780. X
  781. X    get_return(return_address, current-1);
  782. X
  783. X    if (first_word(headers[current-1]->from, "To:")) {
  784. X      strcpy(subject, headers[current-1]->subject);
  785. X      if (form_letter)
  786. X        return_value = mail_filled_in_form(return_address, subject);
  787. X      else
  788. X        return_value = sendmsg(return_address, "", subject, TRUE, NO, TRUE);
  789. X    }
  790. X    else if (headers[current-1]->subject[0] != '\0') {
  791. X      if ((strncmp("Re:", headers[current-1]->subject, 3) == 0) ||
  792. X          (strncmp("RE:", headers[current-1]->subject, 3) == 0) ||
  793. X          (strncmp("re:", headers[current-1]->subject, 3) == 0)) 
  794. X        strcpy(subject, headers[current-1]->subject);
  795. X      else {
  796. X        strcpy(subject,"Re: ");
  797. X        strcat(subject,headers[current-1]->subject); 
  798. X      }
  799. X      if (form_letter)
  800. X        return_value = mail_filled_in_form(return_address, subject);
  801. X      else
  802. X        return_value = sendmsg(return_address, "", subject, TRUE, NO, TRUE);
  803. X    }
  804. X    else
  805. X      if (form_letter)
  806. X        return_value = mail_filled_in_form(return_address, 
  807. X                        "Filled in Form");
  808. X      else
  809. X        return_value = sendmsg(return_address, "", "Re: your mail", 
  810. X                TRUE, NO, TRUE);
  811. X
  812. X    return(return_value);
  813. X}
  814. X
  815. Xint
  816. Xreply_to_everyone()
  817. X{
  818. X    /** Reply to everyone who received the current message.  
  819. X        This includes other people in the 'To:' line and people
  820. X        in the 'Cc:' line too.  Returns non-zero iff the screen 
  821. X            has to be rewritten. **/
  822. X
  823. X    char return_address[SLEN], subject[SLEN];
  824. X    char full_address[VERY_LONG_STRING];
  825. X    int  return_value;
  826. X
  827. X    get_return(return_address, current-1);
  828. X
  829. X    full_address[0] = '\0';            /* no copies yet    */
  830. X    get_and_expand_everyone(return_address, full_address);
  831. X
  832. X    if (headers[current-1]->subject[0] != '\0') {
  833. X      if ((strncmp("Re:", headers[current-1]->subject, 3) == 0) ||
  834. X          (strncmp("RE:", headers[current-1]->subject, 3) == 0) ||
  835. X          (strncmp("re:", headers[current-1]->subject, 3) == 0)) 
  836. X        strcpy(subject, headers[current-1]->subject);
  837. X      else {
  838. X        strcpy(subject,"Re: ");
  839. X        strcat(subject,headers[current-1]->subject); 
  840. X      }
  841. X      return_value = sendmsg(return_address, full_address, subject, 
  842. X                 TRUE, NO, TRUE);
  843. X    }
  844. X    else
  845. X      return_value = sendmsg(return_address, full_address, 
  846. X                  "Re: your mail", TRUE, NO, TRUE);
  847. X
  848. X    return(return_value);
  849. X
  850. X}
  851. X
  852. Xint
  853. Xforward()
  854. X{
  855. X    /** Forward the current message.  What this actually does is
  856. X        to temporarily set forwarding to true, then call 'send' to
  857. X        get the address and route the mail.   Modified to also set
  858. X        'noheader' to FALSE also, so that the original headers
  859. X        of the message sent are included in the message body also.
  860. X        Return TRUE if the main part of the screen has been changed
  861. X        (useful for knowing whether a redraw is needed.
  862. X    **/
  863. X
  864. X    char subject[SLEN], address[VERY_LONG_STRING];
  865. X    int  results, edit_msg = FALSE;
  866. X
  867. X    forwarding = TRUE;
  868. X
  869. X    address[0] = '\0';
  870. X
  871. X    if (headers[current-1]->status & FORM_LETTER)
  872. X      PutLine0(LINES-3,COLUMNS-40,"<No editing allowed.>");
  873. X    else {
  874. X      edit_msg = (want_to("Edit outgoing message? (y/n) ",'y') != 'n');
  875. X    }
  876. X
  877. X    if (strlen(headers[current-1]->subject) > 0) {
  878. X
  879. X      strcpy(subject, headers[current-1]->subject); 
  880. X
  881. X      /* this next strange compare is to see if the last few chars are
  882. X         already '(fwd)' before we tack another on */
  883. X
  884. X      if (strlen(subject) < 6 || (strcmp((char *) subject+strlen(subject)-5,
  885. X                         "(fwd)") != 0))
  886. X        strcat(subject, " (fwd)");
  887. X
  888. X      results = sendmsg(address, "", subject, edit_msg,
  889. X        headers[current-1]->status & FORM_LETTER? 
  890. X        PREFORMATTED : allow_forms, FALSE);
  891. X    }
  892. X    else
  893. X      results = sendmsg(address, "", "Forwarded mail...", edit_msg, 
  894. X        headers[current-1]->status & FORM_LETTER? 
  895. X        PREFORMATTED : allow_forms, FALSE);
  896. X    
  897. X    forwarding = FALSE;
  898. X
  899. X    return(results);
  900. X}
  901. X
  902. Xget_and_expand_everyone(return_address, full_address)
  903. Xchar *return_address, *full_address;
  904. X{
  905. X    /** Read the current message, extracting addresses from the 'To:'
  906. X        and 'Cc:' lines.   As each address is taken, ensure that it
  907. X        isn't to the author of the message NOR to us.  If neither,
  908. X        prepend with current return address and append to the 
  909. X        'full_address' string.
  910. X    **/
  911. X
  912. X    char ret_address[SLEN], buf[SLEN], new_address[SLEN],
  913. X     address[SLEN], comment[SLEN];
  914. X    int  in_message = 1, first_pass = 0, iindex, line_pending = 0;
  915. X
  916. X    /** First off, get to the first line of the message desired **/
  917. X
  918. X    if (fseek(mailfile, headers[current-1]->offset, 0) == -1) {
  919. X    dprint(1,(debugfile,"Error: seek %ld resulted in errno %s (%s)\n", 
  920. X         headers[current-1]->offset, error_name(errno), 
  921. X         "get_and_expand_everyone"));
  922. X    error2("ELM [seek] couldn't read %d bytes into file (%s).",
  923. X           headers[current-1]->offset, error_name(errno));
  924. X    return;
  925. X    }
  926. X    /** okay!  Now we're there!  **/
  927. X
  928. X    /** let's fix the ret_address to reflect the return address of this
  929. X    message with '%s' instead of the persons login name... **/
  930. X
  931. X    translate_return(return_address, ret_address);
  932. X
  933. X    /** now let's parse the actual message! **/
  934. X
  935. X    while (in_message) {
  936. X      if (! line_pending)
  937. X        in_message = (int) (fgets(buf, SLEN, mailfile) != NULL);
  938. X      line_pending = 0;
  939. X      if (first_word(buf, "From ") && first_pass++ != 0) 
  940. X    in_message = FALSE;
  941. X      else if (first_word(buf, "To:") || first_word(buf, "Cc:") ||
  942. X           first_word(buf, "CC:") || first_word(buf, "cc:")) {
  943. X    do {
  944. X      no_ret(buf);
  945. X
  946. X      /** we have a buffer with a list of addresses, each of either the
  947. X          form "address (name)" or "name <address>".  Our mission, should
  948. X          we decide not to be too lazy, is to break it into the two parts.
  949. X      **/
  950. X          
  951. X      if (!whitespace(buf[0]))
  952. X        iindex = chloc(buf, ':')+1;        /* skip header field */
  953. X      else
  954. X        iindex = 0;                /* skip whitespace   */
  955. X
  956. X      while (break_down_tolist(buf, &iindex, address, comment)) {
  957. X
  958. X        if (okay_address(address, return_address)) {
  959. X          sprintf(new_address, ret_address, address);
  960. X          optimize_and_add(new_address, full_address);
  961. X        }
  962. X      }
  963. X
  964. X          in_message = (int) (fgets(buf, SLEN, mailfile) != NULL);
  965. X
  966. X      if (in_message) dprint(2, (debugfile, "> %s", buf));
  967. X    
  968. X    } while (in_message && whitespace(buf[0]));
  969. X    line_pending++;
  970. X      }
  971. X      else if (strlen(buf) < 2)    /* done with header */
  972. X     in_message = FALSE;
  973. X    }
  974. X}
  975. X
  976. Xint
  977. Xokay_address(address, return_address)
  978. Xchar *address, *return_address;
  979. X{
  980. X    /** This routine checks to ensure that the address we just got
  981. X        from the "To:" or "Cc:" line isn't us AND isn't the person    
  982. X        who sent the message.  Returns true iff neither is the case **/
  983. X
  984. X    char our_address[SLEN];
  985. X    struct addr_rec  *alternatives;
  986. X
  987. X    if (in_string(address, return_address))
  988. X      return(FALSE);
  989. X
  990. X    sprintf(our_address, "%s!%s", hostname, username);
  991. X
  992. X    if (in_string(address, our_address))
  993. X      return(FALSE);
  994. X
  995. X    sprintf(our_address, "%s@%s", username, hostname);
  996. X      
  997. X    if (in_string(address, our_address))
  998. X      return(FALSE);
  999. X
  1000. X    alternatives = alternative_addresses;
  1001. X
  1002. X    while (alternatives != NULL) {
  1003. X      if (in_string(address, alternatives->address))
  1004. X        return(FALSE);
  1005. X      alternatives = alternatives->next;
  1006. X    }
  1007. X
  1008. X    return(TRUE);
  1009. X}
  1010. X        
  1011. Xoptimize_and_add(new_address, full_address)
  1012. Xchar *new_address, *full_address;
  1013. X{
  1014. X    /** This routine will add the new address to the list of addresses
  1015. X        in the full address buffer IFF it doesn't already occur.  It
  1016. X        will also try to fix dumb hops if possible, specifically hops
  1017. X        of the form ...a!b...!a... and hops of the form a@b@b etc 
  1018. X    **/
  1019. X
  1020. X    register int len, host_count = 0, i;
  1021. X    char     hosts[MAX_HOPS][SLEN];    /* array of machine names */
  1022. X    char     *host, *addrptr;
  1023. X
  1024. X    if (in_string(full_address, new_address))
  1025. X      return(1);    /* duplicate address */
  1026. X
  1027. X    /** optimize **/
  1028. X    /*  break down into a list of machine names, checking as we go along */
  1029. X    
  1030. X    addrptr = (char *) new_address;
  1031. X
  1032. X    while ((host = get_token(addrptr, "!", 1)) != NULL) {
  1033. X      for (i = 0; i < host_count && ! equal(hosts[i], host); i++)
  1034. X          ;
  1035. X
  1036. X      if (i == host_count) {
  1037. X        strcpy(hosts[host_count++], host);
  1038. X        if (host_count == MAX_HOPS) {
  1039. X           dprint(2, (debugfile,
  1040. X              "Error: hit max_hops limit trying to build return address (%s)\n",
  1041. X              "optimize_and_add"));
  1042. X           error("Can't build return address. Hit MAX_HOPS limit!");
  1043. X           return(1);
  1044. X        }
  1045. X      }
  1046. X      else 
  1047. X        host_count = i + 1;
  1048. X      addrptr = NULL;
  1049. X    }
  1050. X
  1051. X    /** fix the ARPA addresses, if needed **/
  1052. X    
  1053. X    if (chloc(hosts[host_count-1], '@') > -1)
  1054. X      fix_arpa_address(hosts[host_count-1]);
  1055. X      
  1056. X    /** rebuild the address.. **/
  1057. X
  1058. X    new_address[0] = '\0';
  1059. X
  1060. X    for (i = 0; i < host_count; i++)
  1061. X      sprintf(new_address, "%s%s%s", new_address, 
  1062. X              new_address[0] == '\0'? "" : "!",
  1063. X              hosts[i]);
  1064. X
  1065. X    if (full_address[0] == '\0')
  1066. X      strcpy(full_address, new_address);
  1067. X    else {
  1068. X      len = strlen(full_address);
  1069. X      full_address[len  ] = ',';
  1070. X      full_address[len+1] = ' ';
  1071. X      full_address[len+2] = '\0';
  1072. X      strcat(full_address, new_address);
  1073. X    }
  1074. X
  1075. X    return(0);
  1076. X}
  1077. X
  1078. Xget_return_name(address, name, trans_to_lowercase)
  1079. Xchar *address, *name;
  1080. Xint   trans_to_lowercase;
  1081. X{
  1082. X    /** Given the address (either a single address or a combined list 
  1083. X        of addresses) extract the login name of the first person on
  1084. X        the list and return it as 'name'.  Modified to stop at
  1085. X        any non-alphanumeric character. **/
  1086. X
  1087. X    /** An important note to remember is that it isn't vital that this
  1088. X        always returns just the login name, but rather that it always
  1089. X        returns the SAME name.  If the persons' login happens to be,
  1090. X        for example, joe.richards, then it's arguable if the name 
  1091. X        should be joe, or the full login.  It's really immaterial, as
  1092. X        indicated before, so long as we ALWAYS return the same name! **/
  1093. X
  1094. X    /** Another note: modified to return the argument as all lowercase
  1095. X        always, unless trans_to_lowercase is FALSE... **/
  1096. X
  1097. X    char single_address[SLEN];
  1098. X    register int i, loc, iindex = 0;
  1099. X
  1100. X    dprint(6, (debugfile,"get_return_name called with (%s, <>, shift=%s)\n",
  1101. X           address, onoff(trans_to_lowercase)));
  1102. X
  1103. X    /* First step - copy address up to a comma, space, or EOLN */
  1104. X
  1105. X    for (i=0; address[i] != ',' && ! whitespace(address[i]) && 
  1106. X         address[i] != '\0'; i++)
  1107. X      single_address[i] = address[i];
  1108. X    single_address[i] = '\0';
  1109. X
  1110. X    /* Now is it an ARPA address?? */
  1111. X
  1112. X    if ((loc = chloc(single_address, '@')) != -1) {      /* Yes */
  1113. X
  1114. X      /* At this point the algorithm is to keep shifting our copy 
  1115. X         window left until we hit a '!'.  The login name is then
  1116. X             located between the '!' and the first metacharacter to 
  1117. X         it's right (ie '%', ':' or '@'). */
  1118. X
  1119. X      for (i=loc; single_address[i] != '!' && i > -1; i--)
  1120. X          if (single_address[i] == '%' || 
  1121. X              single_address[i] == ':' ||
  1122. X          single_address[i] == '@') loc = i-1;
  1123. X    
  1124. X      if (i < 0 || single_address[i] == '!') i++;
  1125. X
  1126. X      for (iindex = 0; iindex < loc - i + 1; iindex++)
  1127. X        if (trans_to_lowercase)
  1128. X          name[iindex] = tolower(single_address[iindex+i]);
  1129. X        else
  1130. X          name[iindex] = single_address[iindex+i];
  1131. X      name[iindex] = '\0';
  1132. X    }
  1133. X    else {    /* easier - standard USENET address */
  1134. X
  1135. X      /* This really is easier - we just cruise left from the end of
  1136. X         the string until we hit either a '!' or the beginning of the
  1137. X             line.  No sweat. */
  1138. X
  1139. X      loc = strlen(single_address)-1;     /* last char */
  1140. X
  1141. X      for (i = loc; single_address[i] != '!' && single_address[i] != '.' 
  1142. X           && i > -1; i--)
  1143. X         if (trans_to_lowercase)
  1144. X           name[iindex++] = tolower(single_address[i]);
  1145. X         else
  1146. X           name[iindex++] = single_address[i];
  1147. X      name[iindex] = '\0';
  1148. X      reverse(name);
  1149. X    }
  1150. X}
  1151. X
  1152. Xint
  1153. Xbreak_down_tolist(buf, iindex, address, comment)
  1154. Xchar *buf, *address, *comment;
  1155. Xint  *iindex;
  1156. X{
  1157. X    /** This routine steps through "buf" and extracts a single address
  1158. X        entry.  This entry can be of any of the following forms;
  1159. X
  1160. X        address (name)
  1161. X        name <address>
  1162. X        address
  1163. X    
  1164. X        Once it's extracted a single entry, it will then return it as
  1165. X        two tokens, with 'name' (e.g. comment) surrounded by parens.
  1166. X        Returns ZERO if done with the string...
  1167. X    **/
  1168. X
  1169. X    char buffer[LONG_STRING];
  1170. X    register int i, loc = 0, hold_index;
  1171. X
  1172. X    if (*iindex > strlen(buf)) return(FALSE);
  1173. X
  1174. X    while (whitespace(buf[*iindex])) (*iindex)++;
  1175. X
  1176. X    if (*iindex > strlen(buf)) return(FALSE);
  1177. X
  1178. X    /** Now we're pointing at the first character of the token! **/
  1179. X
  1180. X    hold_index = *iindex;
  1181. X
  1182. X    while (buf[*iindex] != ',' && buf[*iindex] != '\0')
  1183. X      buffer[loc++] = buf[(*iindex)++];
  1184. X
  1185. X    (*iindex)++;
  1186. X    buffer[loc] = '\0';
  1187. X
  1188. X    while (whitespace(buffer[loc]))     /* remove trailing whitespace */
  1189. X      buffer[--loc] = '\0';
  1190. X
  1191. X    if (strlen(buffer) == 0) return(FALSE);
  1192. X
  1193. X    dprint(5, (debugfile, "\n* got \"%s\"\n", buffer));
  1194. X
  1195. X    if (buffer[loc-1] == ')') {    /*   address (name)  format */
  1196. X      for (loc = 0;buffer[loc] != '(' && loc < strlen(buffer); loc++)
  1197. X        /* get to the opening comment character... */ ;
  1198. X
  1199. X      loc--;    /* back up to just before the paren */
  1200. X      while (whitespace(buffer[loc])) loc--;    /* back up */
  1201. X
  1202. X      /** get the address field... **/
  1203. X
  1204. X      for (i=0; i <= loc; i++)
  1205. X        address[i] = buffer[i];
  1206. X      address[i] = '\0';
  1207. X
  1208. X      /** now get the comment field, en toto! **/
  1209. X
  1210. X      loc = 0;
  1211. X
  1212. X      for (i = chloc(buffer, '('); i < strlen(buffer); i++)
  1213. X        comment[loc++] = buffer[i];
  1214. X      comment[loc] = '\0';
  1215. X    }
  1216. X    else if (buffer[loc-1] == '>') {    /*   name <address>  format */
  1217. X      dprint(7, (debugfile, "\tcomment <address>\n"));
  1218. X      for (loc = 0;buffer[loc] != '<' && loc < strlen(buffer); loc++)
  1219. X        /* get to the opening comment character... */ ;
  1220. X      while (whitespace(buffer[loc])) loc--;    /* back up */
  1221. X
  1222. X      /** get the comment field... **/
  1223. X
  1224. X      comment[0] = '(';
  1225. X      for (i=1; i < loc; i++)
  1226. X        comment[i] = buffer[i-1];
  1227. X      comment[i++] = ')';
  1228. X      comment[i] = '\0';
  1229. X
  1230. X      /** now get the address field, en toto! **/
  1231. X
  1232. X      loc = 0;
  1233. X
  1234. X      for (i = chloc(buffer,'<') + 1; i < strlen(buffer) - 1; i++)
  1235. X        address[loc++] = buffer[i];
  1236. X    
  1237. X      address[loc] = '\0';
  1238. X    }
  1239. X    else {
  1240. X      /** the next section is added so that all To: lines have commas
  1241. X          in them accordingly **/
  1242. X
  1243. X      for (i=0; buffer[i] != '\0'; i++)
  1244. X        if (whitespace(buffer[i])) break;
  1245. X      if (i < strlen(buffer)) {    /* shouldn't be whitespace */
  1246. X        buffer[i] = '\0';
  1247. X        *iindex = hold_index + strlen(buffer) + 1;
  1248. X      }
  1249. X      strcpy(address, buffer);
  1250. X      comment[0] = '\0';
  1251. X    }
  1252. X
  1253. X    dprint(5, (debugfile, "-- returning '%s' '%s'\n", address, comment));
  1254. X
  1255. X    return(TRUE);
  1256. X}
  1257. SHAR_EOF
  1258. chmod 0444 src/reply.c || echo "restore of src/reply.c fails"
  1259. echo "x - extracting src/returnadd.c (Text)"
  1260. sed 's/^X//' << 'SHAR_EOF' > src/returnadd.c &&
  1261. X
  1262. Xstatic char rcsid[] = "@(#)$Id: returnadd.c,v 2.8 89/03/25 21:47:08 syd Exp $";
  1263. X
  1264. X/*******************************************************************************
  1265. X *  The Elm Mail System  -  $Revision: 2.8 $   $State: Exp $
  1266. X *
  1267. X *             Copyright (c) 1986, 1987 Dave Taylor
  1268. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1269. X *******************************************************************************
  1270. X * Bug reports, patches, comments, suggestions should be sent to:
  1271. X *
  1272. X *    Syd Weinstein, Elm Coordinator
  1273. X *    elm@dsinc.UUCP            dsinc!elm
  1274. X *
  1275. X *******************************************************************************
  1276. X * $Log:    returnadd.c,v $
  1277. X * Revision 2.8  89/03/25  21:47:08  syd
  1278. X * Initial 2.2 Release checkin
  1279. X * 
  1280. X * 
  1281. X ******************************************************************************/
  1282. X
  1283. X/** This set of routines is used to generate real return addresses
  1284. X    and also return addresses suitable for inclusion in a users
  1285. X    alias files (ie optimized based on the pathalias database).
  1286. X
  1287. X**/
  1288. X
  1289. X#include "headers.h"
  1290. X
  1291. X#include <errno.h>
  1292. X
  1293. X#include <sys/types.h>
  1294. X#include <sys/stat.h>
  1295. X
  1296. Xchar *shift_lower();
  1297. X
  1298. Xextern int errno;
  1299. X
  1300. Xchar *error_name(), *strcat(), *strcpy();
  1301. X
  1302. X#ifdef OPTIMIZE_RETURN
  1303. X
  1304. Xoptimize_return(address)
  1305. Xchar *address;
  1306. X{
  1307. X    /** This routine tries to create an optimized address, that is,
  1308. X        an address that has the minimal information needed to 
  1309. X        route a message to this person given the current path
  1310. X        database...
  1311. X    **/
  1312. X
  1313. X#ifndef INTERNET
  1314. X    char    bogus_internet[SLEN];
  1315. X
  1316. X    sprintf(bogus_internet, "@%s%s", hostname, hostdomain);
  1317. X
  1318. X    /** first off, let's see if we need to strip off the localhost
  1319. X        address crap... **/
  1320. X
  1321. X    /** if we have a uucp part (e.g.a!b) AND the bogus address...**/
  1322. X
  1323. X    if (chloc(address,'!') != -1 && in_string(address, bogus_internet))
  1324. X      address[strlen(address)-strlen(bogus_internet)] = '\0';
  1325. X#endif
  1326. X
  1327. X    /** next step is to figure out what sort of address we have... **/
  1328. X
  1329. X    if (chloc(address, '%') != -1)
  1330. X      optimize_cmplx_arpa(address);
  1331. X    else if (chloc(address, '@') != -1)
  1332. X      optimize_arpa(address);
  1333. X    else
  1334. X      optimize_usenet(address);
  1335. X}
  1336. X
  1337. Xoptimize_cmplx_arpa(address)
  1338. Xchar *address;
  1339. X{
  1340. X    /** Try to optimize a complex ARPA address.  A Complex address is one 
  1341. X        that contains '%' (deferred '@').  For example:  
  1342. X        veeger!hpcnof!hplabs!joe%sytech@syte  
  1343. X        is a complex address (no kidding, right?).  The algorithm for 
  1344. X        trying to resolve it is to move all the way to the right, then 
  1345. X        back up left until the first '!' then from there to the SECOND 
  1346. X        metacharacter on the right is the name@host address...(in this 
  1347. X            example, it would be "joe%sytech").  Check this in the routing
  1348. X        table.  If not present, keep backing out to the right until we
  1349. X        find a host that is present, or we hit the '@' sign.  Once we
  1350. X        have a 'normal' ARPA address, hand it to optimize_arpa().
  1351. X    **/
  1352. X
  1353. X    char name[NLEN], buffer[SLEN], junk[SLEN];
  1354. X    char host[NLEN], old_host[NLEN];
  1355. X    register int i, loc, nloc = 0, hloc = 0, passes = 1;
  1356. X
  1357. X    /** first off, get the name%host... **/
  1358. X
  1359. X    for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--)
  1360. X       ;
  1361. X
  1362. X    while (address[loc] != '\0') {
  1363. X
  1364. X      if (passes == 1) {
  1365. X        loc++;
  1366. X
  1367. X        while (address[loc] != '%' && address[loc] != '@')
  1368. X          name[nloc++] = address[loc++];
  1369. X      }
  1370. X      else {
  1371. X        for (i=0; old_host[i] != '\0'; i++)
  1372. X          name[nloc++] = old_host[i];
  1373. X      }
  1374. X
  1375. X      loc++;
  1376. X  
  1377. X      while (address[loc] != '%' && address[loc] != '@')
  1378. X        host[hloc++] = address[loc++];
  1379. X  
  1380. X      host[hloc] = name[nloc] = '\0';
  1381. X
  1382. X      strcpy(old_host, host);
  1383. X
  1384. X      sprintf(buffer, "%s@%s", name, shift_lower(host));
  1385. X
  1386. X      if (expand_site(buffer, junk) == 0) {
  1387. X        strcpy(address, buffer);
  1388. X        return;
  1389. X      }
  1390. X      else if (address[loc] == '@') {
  1391. X        optimize_arpa(address);
  1392. X        return;
  1393. X      }
  1394. X      else
  1395. X        name[nloc++] = '%';    /* for next pass through */
  1396. X
  1397. X    }
  1398. X}
  1399. X
  1400. Xoptimize_arpa(address)
  1401. Xchar *address;
  1402. X{
  1403. X    /** Get an arpa address and simplify it to the minimal
  1404. X        route needed to get mail to this person... **/
  1405. X
  1406. X    char name[NLEN], buffer[SLEN], junk[SLEN];
  1407. X    char host[NLEN];
  1408. X    register int loc, nloc = 0, hloc = 0, at_sign = 0;
  1409. X
  1410. X    for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--) {
  1411. X      if (address[loc] == '@')
  1412. X         at_sign++;    /* remember this spot! */
  1413. X      else if (at_sign)
  1414. X        name[nloc++] = address[loc];
  1415. X      else
  1416. X        host[hloc++] = address[loc];
  1417. X    }
  1418. X
  1419. X    name[nloc] = host[hloc] = '\0';
  1420. X
  1421. X    reverse(name);
  1422. X    reverse(host);
  1423. X
  1424. X    sprintf(buffer,"%s@%s", name, shift_lower(host));
  1425. X
  1426. X    if (expand_site(buffer, junk) == 0) {
  1427. X      strcpy(address, buffer);
  1428. X      return;
  1429. X    }
  1430. X
  1431. X    optimize_usenet(address);    /* that didn't work... */
  1432. X}
  1433. X    
  1434. Xoptimize_usenet(address)
  1435. Xchar *address;
  1436. X{
  1437. X    /** optimize the return address IFF it's a standard usenet
  1438. X        address...
  1439. X    **/
  1440. X
  1441. X    char name[NLEN],  new_address[SLEN], buffer[SLEN], junk[SLEN];
  1442. X    register int loc, nloc = 0, aloc = 0, passes = 1;
  1443. X
  1444. X    for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--) 
  1445. X      name[nloc++] = address[loc];
  1446. X    name[nloc] = '\0';
  1447. X
  1448. X    reverse(name);
  1449. X
  1450. X    new_address[0] = '\0';    
  1451. X
  1452. X    /* got name, now get machine until we can get outta here */
  1453. X
  1454. X    while (loc > -1) {
  1455. X
  1456. X      new_address[aloc++] = address[loc--];    /* the '!' char */
  1457. X
  1458. X      while (address[loc] != '!' && loc > -1)
  1459. X        new_address[aloc++] = address[loc--];
  1460. X
  1461. X      new_address[aloc] = '\0';
  1462. X
  1463. X      strcpy(buffer, new_address);
  1464. X      reverse(buffer);
  1465. X    
  1466. X      if (expand_site(buffer, junk) == 0) {
  1467. X        if (passes == 1 && chloc(name, '@') == -1) {
  1468. X          buffer[strlen(buffer) - 1] = '\0';    /* remove '!' */
  1469. X          sprintf(address, "%s@%s", name, buffer);
  1470. X        }
  1471. X        else 
  1472. X          sprintf(address, "%s%s", buffer, name);
  1473. X        return;        /* success! */
  1474. X      }
  1475. X      passes++;
  1476. X    }
  1477. X
  1478. X    return;        /* nothing to do! */
  1479. X}
  1480. X
  1481. X#endif    /* OPTIMIZE_RETURN */
  1482. X
  1483. Xget_return(buffer, msgnum)
  1484. Xchar *buffer;
  1485. Xint msgnum;
  1486. X{
  1487. X    /** reads msgnum message again, building up the full return 
  1488. X        address including all machines that might have forwarded 
  1489. X        the message.  **/
  1490. X
  1491. X    char buf[SLEN], name1[SLEN], name2[SLEN], lastname[SLEN];
  1492. X    char hold_return[SLEN], alt_name2[SLEN], *cptr;
  1493. X    int ok = 1, lines;
  1494. X
  1495. X    /* now initialize all the char buffers [thanks Keith!] */
  1496. X
  1497. X    buf[0] = name1[0] = name2[0] = lastname[0] = '\0';
  1498. X    hold_return[0] = alt_name2[0] = '\0';
  1499. X
  1500. X    /** get to the first line of the message desired **/
  1501. X
  1502. X    if(msgnum < 0 || msgnum >= message_count || message_count < 1) {
  1503. X      dprint(1, (debugfile,
  1504. X        "Error: %d not a valid message number message_count = %d (%s)",
  1505. X        msgnum, message_count, "get_return"));
  1506. X      error1("%d not a valid message number!");
  1507. X      return;
  1508. X    }
  1509. X
  1510. X    if (fseek(mailfile, headers[msgnum]->offset, 0) == -1) {
  1511. X      dprint(1, (debugfile,
  1512. X        "Error: seek %ld bytes into file hit errno %s (%s)", 
  1513. X        headers[msgnum]->offset, error_name(errno), 
  1514. X            "get_return"));
  1515. X      error2("Couldn't seek %d bytes into file (%s).",
  1516. X           headers[msgnum]->offset, error_name(errno));
  1517. X      return;
  1518. X    }
  1519. X    /** okay!  Now we're there!  **/
  1520. X
  1521. X    lines = headers[msgnum]->lines;
  1522. X
  1523. X    buffer[0] = '\0';
  1524. X
  1525. X    while (ok && lines) {
  1526. X      ok = (int) (fgets(buf, SLEN, mailfile) != NULL);
  1527. X      if (ok) 
  1528. X        if(buffer[strlen(buffer)-1] == '\n') lines--; /* got a full line */
  1529. X      if (first_word(buf, "From ")) 
  1530. X        sscanf(buf, "%*s %s", hold_return);
  1531. X      else if (first_word(buf, ">From")) {
  1532. X        sscanf(buf,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s %s", 
  1533. X               name1, name2, alt_name2);
  1534. X        if (strcmp(name2, "from") == 0)        /* remote from xyz  */
  1535. X          strcpy(name2, alt_name2);
  1536. X        else if (strcmp(name2, "by") == 0)    /* forwarded by xyz */
  1537. X          strcpy(name2, alt_name2);
  1538. X        add_site(buffer, name2, lastname);
  1539. X      }
  1540. X
  1541. X#ifdef USE_EMBEDDED_ADDRESSES
  1542. X
  1543. X      else if (first_word(buf, "From:")) {
  1544. X        get_address_from("From:", buf, hold_return);
  1545. X        buffer[0] = '\0';
  1546. X          }
  1547. X          else if (first_word(buf, "Reply-To:")) {
  1548. X        get_address_from("Reply-To:", buf, buffer);
  1549. X        return;
  1550. X          }
  1551. X
  1552. X#endif
  1553. X
  1554. X      else if (strlen(buf) < 2)    /* done with header */
  1555. X            lines = 0; /* let's get outta here!  We're done!!! */
  1556. X    }
  1557. X
  1558. X    if (buffer[0] == '\0')
  1559. X      strcpy(buffer, hold_return); /* default address! */
  1560. X    else
  1561. X      add_site(buffer, name1, lastname);    /* get the user name too! */
  1562. X
  1563. X    if ((ok = chloc(buffer, '!')) >= 0)
  1564. X        {
  1565. X        strcpy(buf, hostname);
  1566. X        strcat(buf, "!");
  1567. X        if (strncmp(buf, buffer, strlen(buf)) == 0) /* strip off our node name */
  1568. X            {
  1569. X            strcpy(buf, buffer);
  1570. X            strcpy(buffer, &buf[ok + 1]);
  1571. X            }
  1572. X        }
  1573. X
  1574. X    if ((ok = chloc(buffer, '@')) >= 0)
  1575. X        {
  1576. X        sprintf(buf, "%s%s", hostname, hostdomain);
  1577. X        if (strcmp(&buffer[ok+1], buf) == 0         /* @host.dom */
  1578. X         || strcmp(&buffer[ok+1], hostname) == 0)   /* @host */
  1579. X            buffer[ok] = '\0';
  1580. X        }
  1581. X
  1582. X    if (first_word(buffer, "To:"))    /* response to savecopy!  */
  1583. X      get_existing_address(buffer,msgnum);
  1584. X        else 
  1585. X          /* if we have a space character, or we DON'T have '!' or '@' chars */
  1586. X
  1587. X          if (chloc(headers[msgnum]->from, ' ') >= 0 ||
  1588. X         (chloc(headers[msgnum]->from, '!') < 0 &&
  1589. X          chloc(headers[msgnum]->from, '@') < 0)) {
  1590. X           sprintf(name2, " (%s)", headers[msgnum]->from);
  1591. X           strcat(buffer, name2);
  1592. X          }
  1593. X}
  1594. X
  1595. Xget_existing_address(buffer, msgnum)
  1596. Xchar *buffer;
  1597. Xint msgnum;
  1598. X{
  1599. X    /** This routine is called when the message being responded to has
  1600. X        "To:xyz" as the return address, signifying that this message is
  1601. X        an automatically saved copy of a message previously sent.  The
  1602. X        correct to address can be obtained fairly simply by reading the
  1603. X        To: header from the message itself and (blindly) copying it to
  1604. X        the given buffer.  Note that this header can be either a normal
  1605. X        "To:" line (Elm) or "Originally-To:" (previous versions e.g.Msg)
  1606. X    **/
  1607. X
  1608. X    char mybuf[LONG_STRING];
  1609. X    register char ok = 1, in_to = 0;
  1610. X
  1611. X    buffer[0] = '\0';
  1612. X
  1613. X    /** first off, let's get to the beginning of the message... **/
  1614. X
  1615. X    if(msgnum < 0 || msgnum >= message_count || message_count < 1) {
  1616. X      dprint(1, (debugfile,
  1617. X        "Error: %d not a valid message number message_count = %d (%s)",
  1618. X        msgnum, message_count, "get_existing_address"));
  1619. X      error1("%d not a valid message number!");
  1620. X      return;
  1621. X    }
  1622. X        if (fseek(mailfile, headers[msgnum]->offset, 0) == -1) {
  1623. X        dprint(1, (debugfile, 
  1624. X            "Error: seek %ld bytes into file hit errno %s (%s)", 
  1625. X            headers[msgnum]->offset, error_name(errno), 
  1626. X            "get_existing_address"));
  1627. X        error2("Couldn't seek %d bytes into the file (%s).",
  1628. X               headers[msgnum]->offset, error_name(errno));
  1629. X        return;
  1630. X        }
  1631. X        /** okay!  Now we're there!  **/
  1632. X
  1633. X        while (ok) {
  1634. X          ok = (int) (fgets(mybuf, LONG_STRING, mailfile) != NULL);
  1635. X      no_ret(mybuf);    /* remove return character */
  1636. X
  1637. X          if (first_word(mybuf, "To: ")) {
  1638. X        in_to = TRUE;
  1639. X        strcpy(buffer, (char *) mybuf + strlen("To: "));
  1640. X          }
  1641. X      else if (first_word(mybuf, "Original-To:")) {
  1642. X        in_to = TRUE;
  1643. X        strcpy(buffer, (char *) mybuf + strlen("Original-To:"));
  1644. X      }
  1645. X      else if (in_to && whitespace(mybuf[0])) {
  1646. X        strcat(buffer, " ");        /* tag a space in   */
  1647. X        strcat(buffer, (char *) mybuf + 1);    /* skip 1 whitespace */
  1648. X      }
  1649. X      else if (strlen(mybuf) < 2)
  1650. X        return;                /* we're done for!  */
  1651. X      else
  1652. X        in_to = 0;
  1653. X      }
  1654. X}
  1655. SHAR_EOF
  1656. chmod 0444 src/returnadd.c || echo "restore of src/returnadd.c fails"
  1657. echo "x - extracting src/save_opts.c (Text)"
  1658. sed 's/^X//' << 'SHAR_EOF' > src/save_opts.c &&
  1659. X
  1660. Xstatic char rcsid[] = "@(#)$Id: save_opts.c,v 2.17 89/03/25 21:47:09 syd Exp $";
  1661. X
  1662. X/*******************************************************************************
  1663. X *  The Elm Mail System  -  $Revision: 2.17 $   $State: Exp $
  1664. X *
  1665. X *             Copyright (c) 1986, 1987 Dave Taylor
  1666. X *             Copyright (c) 1988, 1989 USENET Community Trust
  1667. X *******************************************************************************
  1668. SHAR_EOF
  1669. echo "End of part 19"
  1670. echo "File src/save_opts.c is continued in part 20"
  1671. echo "20" > s2_seq_.tmp
  1672. exit 0
  1673.  
  1674.